﻿#pragma once
#ifndef _BEHAVIOR_H_
#define _BEHAVIOR_H_
#include <queue>
#include <vector>
#include <ctime>
#include "behavior_define.h"

namespace bt
{
//base action
class Behavior
{
public:
	using Ptr = std::shared_ptr<Behavior>;
	Behavior();
	~Behavior();

	//执行一次行为
	STATE Tick();
	STATE GetStatus()const;
	bool IsRunning()const;
	const char* GetName() const;
protected:
	virtual STATE Update() = 0;
	virtual void Init() { status_ = RUNNING; };
	virtual void Terminate() {};
	void SetName(const char *name);
private:
	STATE status_ = INVALID;
	const char *name_ = nullptr;
};

//条件节点
class Condition : public Behavior
{
public:
	Condition(bool isOk):isOk_(isOk) {}
	~Condition() {};
protected:
	bool isOk_ = false;
};

//容器
class Composite : public Behavior
{
public:
	Composite() {};
	~Composite() {};
	void AddChild(Behavior *node);
	Behavior* GetChild(int idx);
	int GetChildCount();
protected:
	std::vector<Behavior*> childs_;
};

//顺序容器 从0开始执行到最后一个,全部都成功则返回成功,任意一个失败都失败
class Sequence : public Composite
{
public:
	Sequence() {};
	~Sequence() {};

protected:
	virtual STATE Update();
	int cur_idx = 0;
};

//顺序容器 从0开始执行到最后一个,任意一个成功立即返回成功
class Selector : public Composite
{
public:
	Selector() {}
	~Selector() {};

protected:
	virtual STATE Update();
	int cur_idx = 0;
};

//装饰器
class Decorator : public Behavior
{
public:
	Decorator() {}
	~Decorator() {}
	void SetChild(Behavior *node);
protected:
	Behavior *child_ = nullptr;
};

//重复执行
class Repert : public Decorator
{
public:
	Repert(int limitCount):limitCount_(limitCount) {};
	~Repert(){}
protected:
	virtual STATE Update();
	int count_ = 0;
	int limitCount_ = 0;
};

//超时就会执行一次
class Timeout : public Decorator
{
public:
	Timeout(std::time_t t) {};
	~Timeout() {};
protected:
	virtual STATE Update();
	std::time_t mstime_ = 0;
};

//树, 根节点
class Tree : public Behavior
{
public:
	Tree(Behavior *root = nullptr) :root_(root) {};
	void SetRoot(Behavior *root);

protected:
	virtual STATE Update();
	Behavior *root_;

};

template <class Parent>
class DecoratorBuilder;

//混合生成器
template<class Parent>
class CompositeBuilder
{
public:
	CompositeBuilder(Parent *parent, Composite *node) :parent_(parent), node_(node) {};
	//增加叶子节点
    template <class NodeType, typename... Args>
    CompositeBuilder<Parent> Leaf(Args... args)
    {
        auto child = new NodeType((args)...);
        node_->AddChild(child);
        return *this;
    }

	template <class CompositeType, typename... Args>
    CompositeBuilder<CompositeBuilder<Parent> > DoComposite(Args... args)
    {
        auto child = new CompositeType((args)...);
        node_->AddChild(child);
        return CompositeBuilder<CompositeBuilder<Parent> >(this, child);
    }

    template <class DecoratorType, typename... Args>
    DecoratorBuilder<CompositeBuilder<Parent> > DoDecorator(Args... args)
    {
        auto child = new DecoratorType((args)...);
        node_->AddChild(child);
        return DecoratorBuilder<CompositeBuilder<Parent> >(this, child);
    }

    Parent& end()
    {
        return *parent_;
    }

protected:
	Parent *parent_;
	Composite *node_;
};


template <class Parent>
class DecoratorBuilder
{
public:
    DecoratorBuilder(Parent* parent, Decorator* node) : parent_(parent), node_(node) {}

    template <class NodeType, typename... Args>
    DecoratorBuilder<Parent> Leaf(Args... args)
    {
        auto child = new NodeType((args)...);
        node_->SetChild(child);
        return *this;
    }

    template <class CompositeType, typename... Args>
    CompositeBuilder<DecoratorBuilder<Parent>> DoComposite(Args... args)
    {
        auto child = new CompositeType((args)...);
        node_->SetChild(child);
        return CompositeBuilder<DecoratorBuilder<Parent>>(this, (CompositeType*)child);
    }

    template <class DecoratorType, typename... Args>
    DecoratorBuilder<DecoratorBuilder<Parent>> DoDecorator(Args... args)
    {
        auto child = new DecoratorType((args)...);
        node_->SetChild(child);
        return DecoratorBuilder<DecoratorBuilder<Parent>>(this, (DecoratorType*)child);
    }

    Parent& end()
    {
        return *parent_;
    }

private:
    Parent * parent_;
    Decorator* node_;
};

class Builder
{
public:
    template <class NodeType, typename... Args>
    Builder Leaf(Args... args)
    {
        root_ = new NodeType((args)...);
        return *this;
    }

    template <class CompositeType, typename... Args>
    CompositeBuilder<Builder> DoComposite(Args... args)
    {
        root_ = new CompositeType((args)...);
        return CompositeBuilder<Builder>(this, (CompositeType*)root_);
    }

    template <class DecoratorType, typename... Args>
    DecoratorBuilder<Builder> DoDecorator(Args... args)
    {
        root_ = new DecoratorType((args)...);
        return DecoratorBuilder<Builder>(this, (DecoratorType*)root_);
    }

    Behavior* build()
    {
        auto tree = new Tree();
        tree->SetRoot(root_);
        return tree;
    }

private:
    Behavior *root_;
};


}

#endif

